﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using SerialPortHelperLib;
using System.IO.Ports;
using XChipTool.Enties;
using System.IO;
using XChip_Common;

namespace XChipTool
{
    public partial class XChip_SensorI2cForm : DevExpress.XtraEditors.XtraForm
    {
        public bool portIsOpen = false;
        public event Action<string> SendSensor_i2cClick;
        private SerialPort sPortTemp;
        public SerialPort SPortTemp { get { return sPortTemp; } set { sPortTemp = value; } }
        private bool IsUsbOpen = false;

        #region 单例模式--线程安全        
        // 定义一个静态变量来保存类的实例
        private static XChip_SensorI2cForm _xchip_sensorI2cForm;
        // 定义一个标识确保线程同步
        private static readonly object locker = new object();
        // 定义私有构造函数，使外界不能创建该类实例
        //private XChip_SensorI2cForm()
        //{
        //    InitializeComponent();
        //}
        private XChip_SensorI2cForm(bool isUsbOpen = false)
        {
            IsUsbOpen = isUsbOpen;
            InitializeComponent();
        }
        /// <summary>
        /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
        /// </summary>
        /// <returns></returns>
        public static XChip_SensorI2cForm GetInstance()
        {
            // 当第一个线程运行到这里时，此时会对locker对象 "加锁"，
            // 当第二个线程运行该方法时，首先检测到locker对象为"加锁"状态，该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后（即线程运行完之后）会对该对象"解锁"
            // 双重锁定只需要一句判断就可以了
            if (_xchip_sensorI2cForm == null || _xchip_sensorI2cForm.IsDisposed)
            {
                lock (locker)
                {
                    // 如果类的实例不存在则创建，否则直接返回
                    if (_xchip_sensorI2cForm == null || _xchip_sensorI2cForm.IsDisposed)
                    {
                        _xchip_sensorI2cForm = new XChip_SensorI2cForm();
                    }
                }
            }
            return _xchip_sensorI2cForm;
        }

        public static XChip_SensorI2cForm GetInstance(bool isUsbOpen)
        {
            // 当第一个线程运行到这里时，此时会对locker对象 "加锁"，
            // 当第二个线程运行该方法时，首先检测到locker对象为"加锁"状态，该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后（即线程运行完之后）会对该对象"解锁"
            // 双重锁定只需要一句判断就可以了
            if (_xchip_sensorI2cForm == null || _xchip_sensorI2cForm.IsDisposed)
            {
                lock (locker)
                {
                    // 如果类的实例不存在则创建，否则直接返回
                    if (_xchip_sensorI2cForm == null || _xchip_sensorI2cForm.IsDisposed)
                    {
                        _xchip_sensorI2cForm = new XChip_SensorI2cForm(isUsbOpen);
                    }
                }
            }
            return _xchip_sensorI2cForm;
        }

        #endregion
        /// <summary>
        /// 清理事件绑定，以防止重复绑定
        /// </summary>
        public void ClearEvent()
        {
            SendSensor_i2cClick = null;
        }
        private void btn_SensorRead_Click(object sender, EventArgs e)
        {

            if (portusbBtn.ImageOptions.ImageUri.Uri.Contains("AlignVerticalRight"))
            {
                if (!IsUsbOpen)
                {
                    DevExpress.XtraEditors.XtraMessageBox.Show("USB未打开");
                    return;
                }
                uint pVule = 0x0;
                bool isbool;
                if (IntPtr.Size == 8)
                {
                    isbool = XChipUSB.UsbI2cRead64(Convert.ToUInt32(string.IsNullOrEmpty(sensor_add.Text) ? "0" : sensor_add.Text, 16),
                 Convert.ToUInt32(string.IsNullOrEmpty(sensor_reg.Text) ? "0" : sensor_reg.Text, 16),
                 ref pVule, radioGroup1.SelectedIndex, usbcomboTime.SelectedIndex);
                }
                else
                {
                    isbool = XChipUSB.UsbI2cRead86(Convert.ToUInt32(string.IsNullOrEmpty(sensor_add.Text) ? "0" : sensor_add.Text, 16),
                 Convert.ToUInt32(string.IsNullOrEmpty(sensor_reg.Text) ? "0" : sensor_reg.Text, 16),
                 ref pVule, radioGroup1.SelectedIndex, usbcomboTime.SelectedIndex);
                }
                if (isbool)
                {
                    sensor_val.Text = pVule.ToString("X2");
                }
                return;
            }

            if (!sPortTemp.IsOpen)//串口检测
            {
                DevExpress.XtraEditors.XtraMessageBox.Show("串口未打开");
                return;
            }

            var radio = radioGroup1.SelectedIndex;
            bool ischeck1 = false;
            bool ischeck2 = false;
            bool ischeck3 = false;
            switch (radio)
            {
                case 0: ischeck1 = true; break;
                case 1: ischeck2 = true; break;
                case 2: ischeck3 = true; break;
                default:
                    break;
            }


            try
            {
                ////ReadWriteI2c004e();
                //Sensor_i2c sread = new Sensor_i2c(Convert.ToUInt32(string.IsNullOrEmpty(sensor_add.Text) ? "0" : sensor_add.Text, 16),
                // Convert.ToUInt32(string.IsNullOrEmpty(sensor_reg.Text) ? "0" : sensor_reg.Text, 16),
                // Convert.ToUInt32(string.IsNullOrEmpty(sensor_val.Text) ? "0" : sensor_val.Text, 16),
                // ischeck1, ischeck2, ischeck3,
                // sPortTemp);
                //sread.SendSensor_i2cClick += Sread_SendSensor_i2cClick;
                //sensor_val.Text = sread.HwRead();

                // 确定I2C模式
                Sensor_I2C_Ex.I2CMode mode = Sensor_I2C_Ex.I2CMode.Addr8Data8;
                if (ischeck1) mode = Sensor_I2C_Ex.I2CMode.Addr8Data8;
                else if (ischeck2) mode = Sensor_I2C_Ex.I2CMode.Addr16Data8;
                else if (ischeck3) mode = Sensor_I2C_Ex.I2CMode.Addr16Data16;

                // 获取地址和寄存器值
                uint address = Convert.ToUInt32(string.IsNullOrEmpty(sensor_add.Text) ? "0" : sensor_add.Text, 16);
                uint reg = Convert.ToUInt32(string.IsNullOrEmpty(sensor_reg.Text) ? "0" : sensor_reg.Text, 16);

                // 创建新的Sensor_i2c对象
                Sensor_I2C_Ex sread = new Sensor_I2C_Ex(address, mode, sPortTemp);

                // 注册事件
                sread.SendSensorEvent += Sread_SendSensor_i2cClick;

                // 执行读取操作
                uint result = sread.ReadSensorRegister(reg);
                sensor_val.Text = result.ToString("X2");  // 或者使用 "X4"、"X8" 根据需要的位数
            }
            catch (Exception ex)
            {
                XtraMessageBox.Show(ex.Message + "\r\n请检查输入框中是否存在空格等非法字符", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Sread_SendSensor_i2cClick(string msg)
        {
            SendSensor_i2cClick?.Invoke(msg);
        }

        private void btn_SensorFileWrite_Click(object sender, EventArgs e)
        {

            if (portusbBtn.ImageOptions.ImageUri.Uri.Contains("AlignVerticalRight"))
            {
                if (!IsUsbOpen)
                {
                    DevExpress.XtraEditors.XtraMessageBox.Show("USB未打开");
                    return;
                }
                OpenFileDialog ofd1 = new OpenFileDialog();
                ofd1.Filter = "TXT文件(*.txt)|*.txt|所有文件|*.*";
                ofd1.RestoreDirectory = false;
                if (ofd1.ShowDialog() == DialogResult.OK)
                {
                    var isbool = XChipUSB.UsbI2CWriteFile64(ofd1.FileName, radioGroup1.SelectedIndex);
                    if (isbool)
                    {
                        DevExpress.XtraEditors.XtraMessageBox.Show("文件写入成功！");
                        return;
                    }
                }



                return;
            }


            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "TXT文件(*.txt)|*.txt|所有文件|*.*";
            ofd.RestoreDirectory = false;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                List<uint[]> sensorDataList = new List<uint[]>();
                //List<TreeListValue> sensorDataList = new List<TreeListValue>();
                using (StreamReader sr = new StreamReader(ofd.FileName, Encoding.Default))
                    #region 从文件中获取sensor数据存入sensorDataList中
                    try
                    {
                        {
                            string strTemp = null;
                            while ((strTemp = sr.ReadLine()) != null)
                            {
                                if (strTemp.Contains("//"))//去除注释
                                {
                                    strTemp = strTemp.Remove(strTemp.IndexOf("//"));
                                }
                                strTemp = strTemp.Replace('，', ',').Replace("0x", "").Replace(" ", "");//全换成英文逗号，去掉0x和空格
                                string[] strArrayTemp = strTemp.Split(',');
                                if (strArrayTemp.Count() > 2)
                                {
                                    sensorDataList.Add(new uint[2] { Convert.ToUInt32(strArrayTemp[0], 16), Convert.ToUInt32(strArrayTemp[1], 16) });
                                    //sensorDataList.Add(new TreeListValue { DisplayMember = strArrayTemp[0], ValueMember = strArrayTemp[1] });
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        XtraMessageBox.Show("读文件错误：" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                #endregion

                var radio = radioGroup1.SelectedIndex;
                bool ischeck1 = false;
                bool ischeck2 = false;
                bool ischeck3 = false;
                switch (radio)
                {
                    case 0: ischeck1 = true; break;
                    case 1: ischeck2 = true; break;
                    case 2: ischeck3 = true; break;
                    default:
                        break;
                }
                //WaitBefore.Start("开始下发sensor配置", "努力加载配置中...", 60);
                Sensor_i2c sread = new Sensor_i2c(Convert.ToUInt32(sensor_add.Text, 16), ischeck1, ischeck2, ischeck3, sPortTemp);
                sread.SendSensor_i2cClick += Sread_SendSensor_i2cClick;
                sread.HwWrite(sensorDataList);
                XtraMessageBox.Show("完成");
            }
        }

        private void btnSensorWrite_Click(object sender, EventArgs e)
        {

            if (portusbBtn.ImageOptions.ImageUri.Uri.Contains("AlignVerticalRight"))
            {
                if (!IsUsbOpen)
                {
                    DevExpress.XtraEditors.XtraMessageBox.Show("USB未打开");
                    return;
                }
                bool isbool;
                if (IntPtr.Size == 8)
                {
                    isbool = XChipUSB.UsbI2cWrite64(Convert.ToUInt32(string.IsNullOrEmpty(sensor_add.Text) ? "0" : sensor_add.Text, 16),
                  Convert.ToUInt32(string.IsNullOrEmpty(sensor_reg.Text) ? "0" : sensor_reg.Text, 16),
                  Convert.ToUInt32(string.IsNullOrEmpty(sensor_val.Text) ? "0" : sensor_val.Text, 16),
                  radioGroup1.SelectedIndex, usbcomboTime.SelectedIndex);

                }
                else
                {
                    isbool = XChipUSB.UsbI2cWrite86(Convert.ToUInt32(string.IsNullOrEmpty(sensor_add.Text) ? "0" : sensor_add.Text, 16),
                  Convert.ToUInt32(string.IsNullOrEmpty(sensor_reg.Text) ? "0" : sensor_reg.Text, 16),
                  Convert.ToUInt32(string.IsNullOrEmpty(sensor_val.Text) ? "0" : sensor_val.Text, 16),
                  radioGroup1.SelectedIndex, usbcomboTime.SelectedIndex);
                }
                if (isbool)
                {
                    //sensor_val.Text = pVule.ToString("X2");
                }
                return;
            }




            if (!sPortTemp.IsOpen)//串口检测
            {
                DevExpress.XtraEditors.XtraMessageBox.Show("串口未打开");
                return;
            }
            var radio = radioGroup1.SelectedIndex;
            bool ischeck1 = false;
            bool ischeck2 = false;
            bool ischeck3 = false;
            switch (radio)
            {
                case 0: ischeck1 = true; break;
                case 1: ischeck2 = true; break;
                case 2: ischeck3 = true; break;
                default:
                    break;
            }
            if (isGroupWrite.Checked)
            {
                SerialSend.WriteRegister(0x20000046, (uint)Convert.ToUInt32(sensor_add.Text, 16), sPortTemp);

                SerialSend.WriteRegister(0x20000048, 0x20006b44 & 0xff, sPortTemp);
                SerialSend.WriteRegister(0x20000049, 0x20006b44 >> 8 & 0xff, sPortTemp);
                SerialSend.WriteRegister(0x2000004a, 0x20006b44 >> 16 & 0xff, sPortTemp);
                SerialSend.WriteRegister(0x2000004b, 0x20006b44 >> 24 & 0xff, sPortTemp);

                SerialSend.WriteRegister(0x20000045, Convert.ToUInt32(radio + 2), sPortTemp);

                SerialSend.WriteRegister(0x20000058, 1, sPortTemp);

                List<Byte> temp = new List<byte>();
                temp.Add((byte)(Convert.ToUInt32(sensor_reg.Text, 16) & 0xff));
                temp.Add((byte)(Convert.ToUInt32(sensor_reg.Text, 16) >> 8 & 0xff));
                temp.Add((byte)(Convert.ToUInt32(sensor_val.Text, 16) & 0xff));
                temp.Add((byte)(Convert.ToUInt32(sensor_val.Text, 16) >> 8 & 0xff));


                for (int i = 0; i < temp.Count; i++)
                {
                    SerialSend.WriteRegister((ulong)(0x20006b44 + i), temp[i], sPortTemp);
                }


                SerialSend.WriteRegister(0x20000047, 0x1, sPortTemp);

                System.Threading.Thread.Sleep(50);

                if (SerialSend.ReadRegister(0x20000047, sPortTemp) != 0x0)
                {
                    SerialSend.WriteRegister(0x20001e2d, 0x1, sPortTemp);
                    System.Threading.Thread.Sleep(50);
                    if (SerialSend.ReadRegister(0x20000047, sPortTemp) != 0x0)
                    {
                        XtraMessageBox.Show($"固件卡死！！！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            else
            {
                try
                {
                    ////ReadWriteI2c004e();
                    //Sensor_i2c sread = new Sensor_i2c(Convert.ToUInt32(sensor_add.Text, 16),
                    //        Convert.ToUInt32(sensor_reg.Text, 16),
                    //        Convert.ToUInt32(sensor_val.Text, 16),
                    //        ischeck1, ischeck2, ischeck3,
                    //        sPortTemp);
                    //sread.SendSensor_i2cClick += Sread_SendSensor_i2cClick;
                    //sread.HwWrite();


                    // 确定I2C模式
                    Sensor_I2C_Ex.I2CMode mode = Sensor_I2C_Ex.I2CMode.Addr8Data8;
                    if (ischeck1) mode = Sensor_I2C_Ex.I2CMode.Addr8Data8;
                    else if (ischeck2) mode = Sensor_I2C_Ex.I2CMode.Addr16Data8;
                    else if (ischeck3) mode = Sensor_I2C_Ex.I2CMode.Addr16Data16;

                    // 创建新的Sensor_i2c对象
                    Sensor_I2C_Ex sread = new Sensor_I2C_Ex(
                        Convert.ToUInt32(sensor_add.Text, 16),
                        mode,
                        sPortTemp
                    );

                    // 注册事件
                    sread.SendSensorEvent += Sread_SendSensor_i2cClick;

                    // 执行写入操作
                    sread.WriteSensorRegister(
                        Convert.ToUInt32(sensor_reg.Text, 16),
                        Convert.ToUInt32(sensor_val.Text, 16)
                    );
                }
                catch (Exception ex)
                {
                    XtraMessageBox.Show(ex.Message + "\r\n请检查输入框中是否存在空格等非法字符", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }


        }

        private void XChip_SensorI2cForm_Load(object sender, EventArgs e)
        {
            string[] listusbcomb = new string[] { "立即读写", "EOF中断来后读写", "SOF中断来后读写", "其他时间读写" };
            usbcomboTime.Properties.Items.AddRange(listusbcomb);
            usbcomboTime.Text = listusbcomb[0];
            if (IsUsbOpen)
            {
                portusbBtn.ImageOptions.ImageUri.Uri = "AlignVerticalRight;Size16x16;Office2013";
                usblabtime.Show();
                usbcomboTime.Show();
            }
            else
            {
                portusbBtn.ImageOptions.ImageUri.Uri = "AlignVerticalLeft;Size16x16;Office2013";
                usblabtime.Hide();
                usbcomboTime.Hide();
            }
        }
        /// <summary>
        /// 切换串口还是USB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void portusbBtn_Click(object sender, EventArgs e)
        {
            if (portusbBtn.ImageOptions.ImageUri.Uri.Contains("AlignVerticalLeft"))
            {
                portusbBtn.ImageOptions.ImageUri.Uri = "AlignVerticalRight;Size16x16;Office2013";
                //radioGroup1.Properties.Items.Remove(new DevExpress.XtraEditors.Controls.RadioGroupItem() { Description = "" });
                usblabtime.Show();
                usbcomboTime.Show();
            }
            else
            {
                portusbBtn.ImageOptions.ImageUri.Uri = "AlignVerticalLeft;Size16x16;Office2013";
                usblabtime.Hide();
                usbcomboTime.Hide();
            }
        }

        private void radioGroup1_SelectedIndexChanged(object sender, EventArgs e)
        {
            // 获取当前选中的I2C模式
            var selectedMode = (Sensor_I2C_Ex.I2CMode)radioGroup1.SelectedIndex;

            // 定义输入框长度限制和正则表达式掩码
            int regLength = 0;
            int valLength = 0;

            switch (selectedMode)
            {
                case Sensor_I2C_Ex.I2CMode.Addr8Data8:
                    regLength = 2;
                    valLength = 2;
                    break;

                case Sensor_I2C_Ex.I2CMode.Addr16Data8:
                    regLength = 4;
                    valLength = 2;
                    break;

                case Sensor_I2C_Ex.I2CMode.Addr16Data16:
                    regLength = 4;
                    valLength = 4;
                    break;

                case Sensor_I2C_Ex.I2CMode.Addr32Data16:
                case Sensor_I2C_Ex.I2CMode.Addr32Data32:
                    regLength = 4;
                    valLength = 4;
                    break;

                case Sensor_I2C_Ex.I2CMode.Addr32Data8:
                    regLength = 4;
                    valLength = 2;
                    break;
            }

            // 设置输入框的掩码
            SetInputMask(sensor_reg, regLength);
            SetInputMask(sensor_val, valLength);
        }

        private void SetInputMask(DevExpress.XtraEditors.TextEdit textEdit, int length)
        {
            textEdit.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx;
            textEdit.Properties.Mask.EditMask = $@"[0-9a-fA-F]{{0,{length}}}";
            textEdit.Properties.Mask.UseMaskAsDisplayFormat = true;
        }

    }
}